/*
 * OREKIT-X
 * Copyright 2002-2008 CS Communication & Systemes
 * 
 * Parts of this software package have been licensed to CS
 * Communication & Systemes (CS) under one or more contributor license
 * agreements.  See the NOTICE file distributed with this work for
 * additional information.
 *  
 * This is an experimental copy of OREKIT from www.orekit.org.
 * Please use the original OREKIT from orekit.org for normal work
 * unrelated to this research project.
 * 
 * Licensed under the Apache License, Version 2.0 (the "License"); you
 * may not use this file except in compliance with the License.  You
 * may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
 * implied.  See the License for the specific language governing
 * permissions and limitations under the License.
 */
package ore;

import org.apache.commons.math.geometry.Vector3D;

/** 
 * Simple container for Position/Velocity pairs.  Instances of this
 * class are immutable.
 * 
 * @author Fabien Maussion
 * @author Luc Maisonobe
 */
public class PositionVelocity
    extends Object
    implements java.io.Serializable
{

    public static final PositionVelocity ZERO = new PositionVelocity(Vector3D.ZERO, Vector3D.ZERO);



    public final Vector3D position;
    public final Vector3D velocity;


    public PositionVelocity() {
        super();
        position = Vector3D.ZERO;
        velocity = Vector3D.ZERO;
    }
    /** 
     * @param c Array of position (X, Y, Z) and velocity (X, Y, Z).
     */
    protected PositionVelocity(double[] c){
        super();
        this.position = new Vector3D(c[0],c[1],c[2]);
        this.velocity = new Vector3D(c[3],c[4],c[5]);
    }
    /** Builds a PositionVelocity couple.
     * @param position the position vector (m)
     * @param velocity the velocity vector (m/s)
     */
    public PositionVelocity(final Vector3D position, final Vector3D velocity) {
        this.position = position;
        this.velocity = velocity;
    }

    /** Multiplicative constructor
     * Build a PositionVelocity from another one and a scale factor.
     * The PositionVelocity built will be a * pv
     * @param a scale factor
     * @param pv base (unscaled) PositionVelocity
     */
    public PositionVelocity(final double a, final PositionVelocity pv) {
        this.position = new Vector3D(a, pv.position);
        this.velocity = new Vector3D(a, pv.velocity);
    }

    /** Linear constructor
     * Build a PositionVelocity from two other ones and corresponding scale factors.
     * The PositionVelocity built will be a1 * u1 + a2 * u2
     * @param a1 first scale factor
     * @param pv1 first base (unscaled) PositionVelocity
     * @param a2 second scale factor
     * @param pv2 second base (unscaled) PositionVelocity
     */
    public PositionVelocity(final double a1, final PositionVelocity pv1,
                         final double a2, final PositionVelocity pv2) {
        this.position = new Vector3D(a1, pv1.position, a2, pv2.position);
        this.velocity = new Vector3D(a1, pv1.velocity, a2, pv2.velocity);
    }

    /** Linear constructor
     * Build a PositionVelocity from three other ones and corresponding scale factors.
     * The PositionVelocity built will be a1 * u1 + a2 * u2 + a3 * u3
     * @param a1 first scale factor
     * @param pv1 first base (unscaled) PositionVelocity
     * @param a2 second scale factor
     * @param pv2 second base (unscaled) PositionVelocity
     * @param a3 third scale factor
     * @param pv3 third base (unscaled) PositionVelocity
     */
    public PositionVelocity(final double a1, final PositionVelocity pv1,
                         final double a2, final PositionVelocity pv2,
                         final double a3, final PositionVelocity pv3) {
        this.position = new Vector3D(a1, pv1.position, a2, pv2.position, a3, pv3.position);
        this.velocity = new Vector3D(a1, pv1.velocity, a2, pv2.velocity, a3, pv3.velocity);
    }

    /** Linear constructor
     * Build a PositionVelocity from four other ones and corresponding scale factors.
     * The PositionVelocity built will be a1 * u1 + a2 * u2 + a3 * u3 + a4 * u4
     * @param a1 first scale factor
     * @param pv1 first base (unscaled) PositionVelocity
     * @param a2 second scale factor
     * @param pv2 second base (unscaled) PositionVelocity
     * @param a3 third scale factor
     * @param pv3 third base (unscaled) PositionVelocity
     * @param a4 fourth scale factor
     * @param pv4 fourth base (unscaled) PositionVelocity
     */
    public PositionVelocity(final double a1, final PositionVelocity pv1,
                         final double a2, final PositionVelocity pv2,
                         final double a3, final PositionVelocity pv3,
                         final double a4, final PositionVelocity pv4) {
        this.position = new Vector3D(a1, pv1.position, a2, pv2.position,
                          a3, pv3.position, a4, pv4.position);
        this.velocity = new Vector3D(a1, pv1.velocity, a2, pv2.velocity,
                          a3, pv3.velocity, a4, pv4.velocity);
    }


    /** 
     * @return Position vector (m).
     */
    public final Vector3D getPosition() {
        return this.position;
    }
    /** 
     * @return Velocity vector (m/s).
     */
    public final Vector3D getVelocity() {
        return this.velocity;
    }
    /** 
     * @return String representation of this position/velocity pair
     */
    public final String toString() {
        return new StringBuffer().append('{').append("P(").
                                  append(position.getX()).append(", ").
                                  append(position.getY()).append(", ").
                                  append(position.getZ()).append("), V(").
                                  append(velocity.getX()).append(", ").
                                  append(velocity.getY()).append(", ").
                                  append(velocity.getZ()).append(")}").toString();
    }
}
